import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

///Flutter 事件处理流程,shou shi chong tu  ceshi
///手势冲突处理-只有一个响应

class GestureDetectorConflictTest extends StatelessWidget {
  const GestureDetectorConflictTest({Key? key}) : super(key: key);
///红灰蓝，三个方块事件不一致，灰蓝方块交界处，默认“蓝”事件响应
  @override
  Widget build(BuildContext context) {
    print('down build');
    return Stack(
      children: [
        Listener(
          //GestureDetector2
          onPointerUp: (x) => print("2"), // 监听父组件 tapUp 手势
          child: Container(
            width: 100,
            height: 100,
            color: Colors.red,
            alignment: Alignment.center,
            child: GestureDetector(
              //GestureDetector1
              onTapUp: (x) => print("1"), // 监听子组件 tapUp 手势
              child: Container(
                width: 50,
                height: 50,
                color: Colors.grey,
              ),
            ),
          ),
        ),
        Listener(
          //GestureDetector2
          // onPointerUp: (x) => print("3"), // 监听父组件 tapUp 手势
          // child: Container(
          //   width: 50,
          //   height: 50,
          //   color: Color(0xFF0E2DF6),
          //   alignment: Alignment.center,
          // ),

          ///SizedBox设置 HitTestBehavior.translucent
          ///点击交界处会打印321
          // behavior: HitTestBehavior.translucent,
          // onPointerUp: (x) => print("3"), // 监听父组件 tapUp 手势
          // child: SizedBox(
          //   width: 50,
          //   height: 50,
          // ),
        )
      ],
    );
  }
}

///此示例运行后，每次拖动只会沿一个方向移动（水平或垂直），
///而竞争发生在手指按下后首次移动（move）时，
///此例中具体的“获胜”条件是：首次移动时的位移在水平和垂直方向上的分量大的一个获胜。
class BothDirectionTest extends StatefulWidget {
  @override
  _BothDirectionTestState createState() => _BothDirectionTestState();
}

class _BothDirectionTestState extends State<BothDirectionTest> {
  double _top = 0.0;
  double _left = 0.0;
  double _leftB = 0.0;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Positioned(
          top: _top,
          left: _left,
          child: GestureDetector(
            child: CircleAvatar(child: Text("A")),
            //垂直方向拖动事件
            onVerticalDragUpdate: (DragUpdateDetails details) {
              print("垂直方向拖动事件:$_top");
              setState(() {
                _top += details.delta.dy;
              });
            },
            onHorizontalDragUpdate: (DragUpdateDetails details) {
              print("水平方向拖动事件:$_left");
              setState(() {
                _left += details.delta.dx;
              });
            },
          ),
        ),
        Positioned(
          top:80.0,
          left: _leftB,
          child: Listener(
            onPointerDown: (details) {
              print("down");
            },
            onPointerUp: (details) {
              //会触发
              print("up");
            },
            child: GestureDetector(
              child: CircleAvatar(child: Text("B")),
              onHorizontalDragUpdate: (DragUpdateDetails details) {
                setState(() {
                  _leftB += details.delta.dx;
                });
              },
              onHorizontalDragEnd: (details) {
                print("onHorizontalDragEnd");
              },
            ),
          ),
        )
      ],
    );
  }
}

///假设有一个widget，它可以左右拖动，现在我们也想检测在它上面手指按下和抬起的事件，代码如下：
class GestureConflictTestRoute extends StatefulWidget {
  @override
  _GestureConflictTestRouteState createState() => _GestureConflictTestRouteState();
}

class _GestureConflictTestRouteState extends State<GestureConflictTestRoute> {
  double _left = 0.0;
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Positioned(
          left: _left,
          child: GestureDetector(
            child: CircleAvatar(child: Text("A")), //要拖动和点击的widget
            onHorizontalDragUpdate: (DragUpdateDetails details) {
              setState(() {
                _left += details.delta.dx;
              });
            },

            onHorizontalDragEnd: (details){
              print("onHorizontalDragEnd");
            },
            onTapDown: (details){
              print("down");
            },
            onTapUp: (details){
              print("up");
            },
          ),
        )
      ],
    );
  }
}


///我们先自定义tap手势识别器（Recognizer）：
///自定义手势识别器的方式比较麻烦，原理时当确定手势竞争胜出者时，
///会调用胜出者的acceptGesture 方法，表示“宣布成功”，
///然后会调用其它手势识别其的rejectGesture 方法，表示“宣布失败”。
///既然如此，我们可以自定义手势识别器（Recognizer），
///然后去重写它的rejectGesture 方法：在里面调用acceptGesture 方法，这
///就相当于它失败是强制将它也变成竞争的成功者了，这样它的回调也就会执行。
class CustomTapGestureRecognizer extends TapGestureRecognizer {
  @override
  void rejectGesture(int pointer) {
    //不，我不要失败，我要成功
    //super.rejectGesture(pointer);
    //宣布成功
    super.acceptGesture(pointer);
  }
}

//创建一个新的GestureDetector，用我们自定义的 CustomTapGestureRecognizer 替换默认的
RawGestureDetector customGestureDetector({
  GestureTapUpCallback? onTapUp,
  GestureTapDownCallback? onTapDown,
  Widget? child,
}) {
  return RawGestureDetector(
    child: child,
    gestures: {
      CustomTapGestureRecognizer:
      GestureRecognizerFactoryWithHandlers<CustomTapGestureRecognizer>(
            () => CustomTapGestureRecognizer(),
            (detector) {
          detector.onTapUp = onTapUp;
        },
      )
    },
  );
}

///自定义tap手势识别器的应用
class CustomGestureDetectorConflictTest extends StatelessWidget {
  const CustomGestureDetectorConflictTest({Key? key}) : super(key: key);
  ///红灰蓝，三个方块事件不一致，灰蓝方块交界处，默认“蓝”事件响应
  @override
  Widget build(BuildContext context) {
    print('down build');
    return Stack(
      children: [
        customGestureDetector(
          //GestureDetector2
          onTapUp: (x) => print(" 自定义tap手势识别器的应用 2"), // 监听父组件 tapUp 手势
          child: Container(
            width: 100,
            height: 100,
            color: Colors.red,
            alignment: Alignment.center,
            child: GestureDetector(
              //GestureDetector1
              onTapUp: (x) => print("自定义tap手势识别器的应用 1"), // 监听子组件 tapUp 手势
              child: Container(
                width: 50,
                height: 50,
                color: Colors.grey,
              ),
            ),
          ),
        ),
      ],
    );
  }
}